<?php

namespace app\common\model;

use basic\ModelBasic;
use app\common\model as M;
/**
 * 订单表
 */
class Order extends ModelBasic
{
	use \traits\ModelTrait;

    /* 订单类型【1：购买线路  2：金币商城  3：会员开通  4：升级会员 5:续费会员 】 */
    const ORDER_TYPE_ROUTES   = 1;
    const ORDER_TYPE_GOLDS    = 2;
    const ORDER_TYPE_OPENCARD = 3;
    const ORDER_TYPE_RAISE    = 4;
    const ORDER_TYPE_RENEW    = 5;
    public static $order_type = [
        1    =>    '线路预定',
        2    =>    '金币商城',
        3    =>    '会员开通',
        4    =>    '会员升级',
        5    =>    '会员续费',
    ];

    /** 已支付 */
    const STATUS_PAID = 1;
    const STATUS_PAID_PART = 2;
    public static $pay_status = [
        0    => '未支付',
        1    => '已支付',
        2    => '部分支付',
    ];

    /** 订单状态 */
    const STATUS_VALID   = 1;
    const STATUS_ABOLISH = 2;
    const STATUS_DEPOSIT = 3;
    public static $status = [
        1    => '有效',
        2    => '已作废',
        3    => '已付定金',
    ];

    /** 支付方式 */
    const PAY_WECHAT   = 1;
    const PAY_ALIPAY   = 2;
    const PAY_INTEGRAL = 3;
    const PAY_GOLDS    = 4;
    public static $pay_type = [
        1    =>    '微信支付',
        2    =>    '支付宝支付',
        3    =>    '积分',
        4    =>    '金币',
    ];

    const FROM_MP      = 1;
    const FROM_CHANNEL = 2;
    public static $order_from = [
        1    =>    '小程序',
        2    =>    '视频号',
    ];

	/**
	 * 设置where条件
	 * @Author   FW
	 * @DateTime 2021-01-12
	 * @Email    123763712@qq.com
	 * @param    [type]           $where [description]
	 * @param    string           $alias [description]
	 * @param    [type]           $model [description]
	 */
	public static function setWhere($where,$alias='m',$model=null){
        $model = $model===null ? new self() : $model;

        $model->alias($alias);

        if ( isset($where['pay_type']) && $where['pay_type'] > 0 ) {
            $model->where(sprintf('%s.pay_type = %d' , $alias, $where['pay_type']));
        }

        if ( isset($where['pay_status']) && $where['pay_status'] > 0 ) {
            $model->where(sprintf('%s.pay_status = %d' , $alias, $where['pay_status']));
        }

        if ( isset($where['order_from']) && $where['order_from'] > 0 ) {
            $model->where(sprintf('%s.order_from = %d' , $alias, $where['order_from']));
        }

        if ( isset($where['order_no']) && $where['order_no'] > 0 ) {
            $model->where(sprintf('%s.order_no',$alias) , 'LIKE' , '%'.$where['order_no'].'%' );
        }

        if ( isset($where['uid']) && $where['uid'] > 0 ) {
            $model->where(sprintf('%s.uid = %d' , $alias, $where['uid']));
        }

        if ( isset($where['keyword']) && $where['keyword'] != '' ) {
            $keyword = $where['keyword'];
            $model->where("{$alias}.uid IN (SELECT uid FROM eb_user WHERE ( (full_name LIKE '%{$keyword}%') OR (mobile LIKE '%{$keyword}%') ) )");
        }

        if ( isset($where['order_type']) && $where['order_type'] > 0 ) {
            $model->where(sprintf('%s.order_type = %d' , $alias, $where['order_type']));

            ## 退款类型筛选 ，必定在order type筛选条件下
            if ( isset($where['refund_type']) && $where['refund_type'] > 0 ) {
                $model->where(sprintf('%s.refund_type = %d' , $alias, $where['refund_type']));
            }
        }

        if ( isset($where['date_time']) && strpos($where['date_time'] , ',') ) {
            list($start_time , $end_time) = explode(',' , $where['date_time']);
            if ( $start_time != '' ) {
                $model->where(sprintf("%s.create_time >= '%s'" , $alias , $start_time . ' 00:00:00'));
            }

            if ( $end_time != '' ) {
                $model->where(sprintf("%s.create_time <= '%s'" , $alias , $end_time . ' 23:59:59'));
            }
        }

        return $model;
    }

    /**
     * 列表
     * @Author   FW
     * @DateTime 2020-09-24
     * @Email    123763712@qq.com
     * @param    [type]
     * @return   [type]
     */
    public static function getList($where){
    	$count = self::setWhere($where)->count();
    	$data  = [];
    	if ( $count == 0 ) {
    		return compact('data','count');
    	}

        $obj = self::setWhere($where,'m');
		
		$data = $obj->field("m.id,m.order_no,m.out_trade_no,m.orgn_amt,m.disc_amt,m.order_amt,m.integral,m.golds,m.status,m.pay_type,m.pay_status,m.create_time,m.uid,m.order_type,m.order_outer_id,m.spread_suid,m.spread_uid,m.order_from,m.use_deposit,m.deposit_amt,m.final_amt,ifnull(m.remark,'-') as remark,u.nickname,u.mobile,ifnull(saleu.full_name,saleu.nickname) as order_saler,ifnull(spru.full_name,spru.nickname) as order_spreader")
		->join('__USER__ u' , 'm.uid = u.uid')
        ->join('__USER__ saleu' , 'm.spread_suid = saleu.uid' , 'left')
        ->join('__USER__ spru' , 'm.spread_uid = spru.uid' , 'left')
		->order('m.create_time desc')
		->page($where['page'] ?? 1, $where['limit'] ?? 15)->select();
		
        if ( !empty($data) ) {
        	$data = $data->toArray();
        	$data = static::process_list($data);
        }

        return compact('data','count');
    }

    /**
     * 处理列表数据
     * @Author   FW
     * @DateTime 2021-01-12
     * @Email    123763712@qq.com
     * @param    array            $list [description]
     * @return   [type]                 [description]
     */
    public static function process_list (array $list)
    {
        foreach ($list as $key => &$value) {
            $value['orgn_amt'] *= 1;
            $value['disc_amt'] *= 1;
            $value['order_amt'] *= 1;
            $value['integral'] *= 1;
            $value['golds'] *= 1;

            $value['status_display']      = static::$status[$value['status']] ?? '-';
            $value['pay_type_display']    = static::$pay_type[$value['pay_type']] ?? '-';
            $value['pay_status_display']  = static::$pay_status[$value['pay_status']] ?? '-';
            $value['order_type_display']  = static::$order_type[$value['order_type']] ?? '-';
            $value['order_from_display']  = static::$order_from[$value['order_from']] ?? '-';

            $value['outer']  = [];
			/**
			 *  const ORDER_TYPE_ROUTES   = 1;
			 *	const ORDER_TYPE_GOLDS    = 2;
			 *	const ORDER_TYPE_OPENCARD = 3;
			 *	const ORDER_TYPE_RAISE    = 4;
			 */
			
			if ( $value['order_type'] == self::ORDER_TYPE_ROUTES ) {
				$value['outer'] = OrderOuterRoutes::alias('m')->field('m.id,m.status,r.route_name as outer_title')
                ->join('__ROUTES__ r' , 'm.route_id = r.id')
                ->where('m.id' , $value['order_outer_id'])
                ->find();

				if ( !empty($value['outer']) ) {
					$value['outer']->status_display = OrderOuterRoutes::$status[$value['outer']->status] ?? '-';
				}
			}
			
			if ( $value['order_type'] == self::ORDER_TYPE_GOLDS ) {
				$value['outer'] = OrderOuterExchange::alias('m')->field('m.id,m.status,g.goods_name as outer_title')
                ->join('__GOLDS_GOODS__ g' , 'm.goods_id = g.id')
                ->where('m.id' , $value['order_outer_id'])
                ->find();

				if ( !empty($value['outer']) ) {
					$value['outer']->status_display = OrderOuterExchange::$status[$value['outer']->status] ?? '-';
				}
			}

            if ( $value['order_type'] == self::ORDER_TYPE_OPENCARD ) {
                $value['outer'] = UserLevelRecords::alias('m')->field("m.id,m.is_paid as status,'' as outer_title")->where('id' , $value['order_outer_id'])->find();
                if ( !empty($value['outer']) ) {
                    $value['outer']->status_display = UserLevelRecords::$paid_status[$value['outer']->status] ?? '-';
                }
            }

            if ( $value['order_type'] == self::ORDER_TYPE_RAISE ) {
                $value['outer'] = UserLevelRecords::alias('m')->field("m.id,m.is_paid as status,'' as outer_title")->where('id' , $value['order_outer_id'])->find();
                if ( !empty($value['outer']) ) {
                    $value['outer']->status_display = UserLevelRecords::$paid_status[$value['outer']->status] ?? '-';
                }
            }
            
        }
        return $list;
    }

    /**
     * [getOne description]
     * @Author   FW
     * @DateTime 2021-01-12
     * @Email    123763712@qq.com
     * @param    [type]           $id [description]
     * @return   [type]               [description]
     */
    public static function getOne ($id)
    {
        $item = self::alias('m')
        	->field("m.id,m.order_no,m.out_trade_no,m.orgn_amt,m.disc_amt,m.order_amt,m.integral,m.golds,m.status,m.pay_type,m.pay_status,m.create_time,m.uid,m.order_type,m.order_outer_id,m.spread_uid,m.order_from,m.use_deposit,m.deposit_amt,m.final_amt,ifnull(m.remark,'-') as remark,u.full_name,u.mobile")
			->join('__USER__ u' , 'm.uid = u.uid' , 'left')
            ->where('m.id',$id)
            ->find();

        if ( empty($item) ) {
            return [];
        }

        $item = $item->toArray();

        return static::process_list([$item])[0];
    }

    /**
     * 生成订单号
     * @Author   FW
     * @DateTime 2021-07-27
     * @Email    123763712@qq.com
     * @param    string           $prefix [description]
     * @return   [type]                   [description]
     */
    public static function createOrderNo ( $prefix = '' )
    {
        return strtoupper( substr($prefix,0,2) ) . date('YmdHis') . mt_rand(1000,9999);
    }

     /**
     * 支付成功(支付宝和微信支付回调都会统一走这个方法)
     * @Author   FW
     * @DateTime 2021-05-24
     * @Email    123763712@qq.com
     * @param    [type]           $order_no           [description]
     * @param    [type]           $out_trade_no [description]
     * @return   [type]                         [description]
     */
    public static function paySuccess($order_no, $out_trade_no, $remark = '' )
    {
        self::beginTrans();

        try {
            $order = self::where('order_no', $order_no)->find();

            ## 如果为空检查子订单【订单已被拆分为订单订单和尾款订单】
            if ( empty($order) ) {
                $subOrder = OrderSubs::where('order_no', $order_no)->find();

                if ( !empty($subOrder) ) {
                    $order = self::where('id', $subOrder->order_id)->find();
                    if ( empty($order) ) throw new \Exception("对应主订单不存在");

                    if ( $order->use_deposit != 1 ) throw new \Exception("主订单信息异常");

                    $subOrder->pay_status       = self::STATUS_PAID;
                    $subOrder->pay_time         = date('Y-m-d H:i:s');
                    $subOrder->out_trade_no     = $out_trade_no;
                    $res = $subOrder->save();
                    if ($res === false) throw new \Exception("error 73601");

                    // 付定金-订单完成部分
                    if ( $subOrder->order_type == 1 ) {
                        $order->status       = self::STATUS_DEPOSIT;
                        $order->pay_status   = self::STATUS_PAID_PART;
                        $order->pay_time     = date('Y-m-d H:i:s');
                        $order->out_trade_no = sprintf('%s-%d' , $out_trade_no , $subOrder->order_type);
                        $res = $order->save();
                        if ($res === false) throw new \Exception("error 19201");
                    }

                    // 付尾款-订单完成全部
                    if ( $subOrder->order_type == 2 ) {
                        $order->status       = self::STATUS_VALID;
                        $order->pay_status   = self::STATUS_PAID;
                        $order->pay_time     = date('Y-m-d H:i:s');
                        $order->out_trade_no = sprintf('%s-%d', $order->out_trade_no , $subOrder->order_type);
                        $res = $order->save();
                        if ($res === false) throw new \Exception("error 29801");
                    }

                    ## 02 订单关联实体回调（目前仅有线路订单接受预定）
                    $callback_map = [
                        // ORDER_TYPE_ROUTES 路线预定
                        1    =>    'app\common\model\order\RoutesBook',
                    ];

                    $mapping_name = $callback_map[$order['order_type']] ?? 'stdClass';
                    $obj          = new $mapping_name;

                    if ( method_exists($obj , 'paid_callback') ) {
                        $res = $obj->paid_callback($order);

                        if ($res === false) throw new \Exception("paid_callback 回调失败");
                    }

                    self::commitTrans();
                    return true;
                }
            }

            ## 如果不为空则无子订单，主订单直接处理
            if (!empty($order)) {
                if ($order['pay_status'] == static::STATUS_PAID ) return true;

                ## 01 更新订单状态
                $order->status           = self::STATUS_VALID;
                $order->pay_status       = self::STATUS_PAID;
                $order->pay_time         = date('Y-m-d H:i:s');
                $order->out_trade_no     = $out_trade_no;

                if ( $remark != '' ) $order->remark = $order->remark . ' ,' .$remark.'('.$order->pay_time.')';
                
                $res = $order->save();
                if ($res === false) throw new \Exception("error 01");

                /**
                 *  const ORDER_TYPE_ROUTES   = 1;
                 *  const ORDER_TYPE_GOLDS    = 2;
                 *  const ORDER_TYPE_OPENCARD = 3;
                 *  const ORDER_TYPE_RAISE    = 4;
                 *  const ORDER_TYPE_RENEW    = 5;
                 */

                ## 02 订单关联实体回调
                $callback_map = [
                    // ORDER_TYPE_ROUTES 路线预定
                    1    =>    'app\common\model\order\RoutesBook',
                    // ORDER_TYPE_GOLDS 金币兑换
                    2    =>    'app\common\model\order\GoldsGoods',
                    // ORDER_TYPE_OPENCARD 开卡
                    3    =>    'app\common\model\order\UserActivate',
                    // ORDER_TYPE_RAISE 升卡
                    4    =>    'app\common\model\order\UserRaise',
                    // ORDER_TYPE_RENEW 续费
                    5    =>    'app\common\model\order\UserRenew',
                ];

                $mapping_name = $callback_map[$order['order_type']] ?? 'stdClass';
                $obj          = new $mapping_name;

                if ( method_exists($obj , 'paid_callback') ) {
                    $res = $obj->paid_callback($order);

                    if ($res === false) throw new \Exception("paid_callback 回调失败");
                }

                self::commitTrans();
                return true;
            }
        } catch (\Exception $e) {
            \think\Log::debug($e->getMessage());
            self::rollbackTrans();
            return $e->getMessage();
        }

        self::rollbackTrans();
        return false;
    }

    /**
     * 订单取消：删除订单以及所有关联数据
     * @param  [type] $order_id [description]
     * @return [type]           [description]
     */
    public static function cancel ($order_id)
    {
        ## 01 删除主订单
        $res = self::where('id' , $order_id)->delete();
        if ( $res === false ) throw new \Exception('订单删除失败');

        ## 02 删除订单子项
        $res = M\OrderItems::where('order_id' , $order_id)->delete();
        if ( $res === false ) throw new \Exception('订单子项删除失败');

        ## 03 删除已购套餐
        $res = M\user\BoughtPackage::where('order_id' , $order_id)->delete();
        if ( $res === false ) throw new \Exception('订单已购套餐失败');

        return true;
    }
} //Class End
